package com.jzx.provider.chat.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jzx.provider.chat.dto.Message;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import org.springframework.stereotype.Component;
import org.yeauty.annotation.*;
import org.yeauty.pojo.ParameterMap;
import org.yeauty.pojo.Session;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint(prefix = "netty-websocket")
@Component
public class ChatService {

    private Session session;

    private String key;

    /**
     * 用来记录线程数量
     */
    private static AtomicInteger count = new AtomicInteger(0);

    /**
     * 用来存放每个客户端对应的ChatService对象。
     */
    private static CopyOnWriteArraySet<ChatService> webSockets = new CopyOnWriteArraySet<>();

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String, Session>();
    private String token;

    @OnOpen
    public void onOpen(Session session, HttpHeaders headers, ParameterMap parameterMap) throws IOException {
        this.session = session;
        //加入set中
        webSockets.add(this);
        //把对应用户手机号的session放到sessionPool中，用于单点信息发送
        String token = parameterMap.getParameter("token");
        //获取登录平台
        String plat = parameterMap.getParameter("plat");
        this.key = token;
        sessionPool.put(token, session);
        count.set(sessionPool.size());
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        //连接数量减一
        count.decrementAndGet();
        webSockets.remove(this);
        //移除session
        sessionPool.remove(this.key);
        System.out.println("one connection closed");
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
    }

    @OnMessage
    public void onMessage(Session session, String res) {
        System.out.println(res);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Message book = objectMapper.readValue(res.toString(), Message.class);
        } catch (IOException e) {
            e.printStackTrace();
            session.sendText("消息解析异常！");
        }
        //群发消息 记得加锁
        for (ChatService item : webSockets) {
            try {
                item.sendMessage(res);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @OnBinary
    public void onBinary(Session session, byte[] bytes) {
        for (byte b : bytes) {
            System.out.println(b);
        }
        session.sendBinary(bytes);
    }

    @OnEvent
    public void onEvent(Session session, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    System.out.println("read idle");
                    break;
                case WRITER_IDLE:
                    System.out.println("write idle");
                    break;
                case ALL_IDLE:
                    System.out.println("all idle");
                    break;
                default:
                    break;
            }
        }
    }

    public void sendMessage(String message) throws IOException {
        this.session.sendText(message);
    }
}
